#include <QtTest>
#include "quote_engine.h"
#include "quote_defines.h"
#include "ThostFtdcUserApiStruct.h"

using namespace QuoteEngine;

class QuoteEngineTest : public QObject
{
    Q_OBJECT

private slots:
    void initTestCase();
    void cleanupTestCase();
    void init();
    void cleanup();

    // 基本功能测试
    void testLoginAndLogout();       // 登录登出测试
    void testConnectionTimeout();     // 连接超时测试
    void testSubscription();         // 订阅测试

private:
    Engine* engine;
    QuoteConfig createTestConfig();
    QuoteConfig createTimeoutConfig();
    
    // 用于记录信号
    bool statusChanged{false};
    bool errorReceived{false};
    bool tickReceived{false};        // 添加行情接收标志
    int lastErrorCode{0};
    QString lastErrorMsg;
    ConnectionStatus lastStatus{ConnectionStatus::Disconnected};
    QString lastTickSymbol;          // 添加最后接收的合约代码
    
    // 测试用的合约列表
    const std::vector<QString> TEST_SYMBOLS{"SA505", "ni2405"};
    
    // 辅助函数
    bool waitForStatus(ConnectionStatus expectedStatus, int timeout = 5000);
    bool waitForTick(int timeout = 5000);  // 等待行情数据的辅助函数
};

void QuoteEngineTest::initTestCase()
{
    qDebug() << "Starting QuoteEngine basic tests";
}

void QuoteEngineTest::cleanupTestCase()
{
    qDebug() << "Finishing QuoteEngine basic tests";
}

QuoteConfig QuoteEngineTest::createTestConfig()
{
    QuoteConfig config;
    // config.brokerID = "9999";
    // config.userID = "112537";
    // config.password = "zmin821001";
    // config.frontAddress = "tcp://180.168.146.187:10211";
    // config.flowPath = "/home/leexMarketLib/flow/";
    // config.mdDllPath = "/home/leexMarketLib/include/CTP/thostmduserapi_se.so";

    config.userID = "8641";
    config.password = "123456";  
    config.frontAddress = "tcp://openctp.cn:20004";
    config.flowPath = "/home/leexMarketLib/flow/";
    config.mdDllPath = "/home/leexMarketLib/include/CTP/thostmduserapi_tts.so";
    
    config.connection.enableUdp = false;
    config.connection.heartbeatTimeout = 15;
    
    return config;
}

QuoteConfig QuoteEngineTest::createTimeoutConfig()
{
    QuoteConfig config = createTestConfig();
    // 使用一个确保无法解析的地址
    config.frontAddress = "tcp://non.existent.domain.test:12345";
    // 设置较短的超时时间
    config.connection.heartbeatTimeout = 5;
    return config;
}

void QuoteEngineTest::init()
{
    engine = new Engine(this);
    
    connect(engine, &Engine::onStatusChanged, this, 
        [this](ConnectionStatus status) { 
            statusChanged = true;
            lastStatus = status;
            qDebug() << "Connection status changed:" << getConnectionStatusString(status);
        });
    
    connect(engine, &Engine::onError, this,
        [this](int code, const QString& msg) {
            errorReceived = true;
            lastErrorCode = code;
            lastErrorMsg = msg;
            qDebug() << "Error received:" << code << msg;
        });
        
    connect(engine, &Engine::onTick, this,
        [this](const CThostFtdcDepthMarketDataField& data) {
            tickReceived = true;
            lastTickSymbol = QString::fromLocal8Bit(data.InstrumentID);
            qDebug() << "Tick received for:" << lastTickSymbol
                     << "LastPrice:" << data.LastPrice;
        });
}

void QuoteEngineTest::cleanup()
{
    if (engine) {
        engine->stop();
        delete engine;
        engine = nullptr;
    }
    
    statusChanged = false;
    errorReceived = false;
    tickReceived = false;
    lastErrorCode = 0;
    lastErrorMsg.clear();
    lastStatus = ConnectionStatus::Disconnected;
    lastTickSymbol.clear();
}

bool QuoteEngineTest::waitForStatus(ConnectionStatus expectedStatus, int timeout)
{
    QElapsedTimer timer;
    timer.start();
    
    while (lastStatus != expectedStatus && timer.elapsed() < timeout) {
        QTest::qWait(100);
    }
    
    return lastStatus == expectedStatus;
}

bool QuoteEngineTest::waitForTick(int timeout)
{
    QElapsedTimer timer;
    timer.start();
    
    while (!tickReceived && timer.elapsed() < timeout) {
        QTest::qWait(100);
    }
    
    return tickReceived;
}

void QuoteEngineTest::testLoginAndLogout()
{
    QuoteConfig config = createTestConfig();
    
    // 证动态库文件是否存在
    QVERIFY2(QFile::exists(config.mdDllPath), 
             qPrintable(QString("Library file not found: %1").arg(config.mdDllPath)));
             
    // 初始化
    QVERIFY2(engine->init(config), "Initialization failed");
    QVERIFY(engine->connectionStatus() == ConnectionStatus::Disconnected);
    
    // 测试登录
    engine->start();
    QVERIFY(engine->connectionStatus() == ConnectionStatus::Connecting);
    QVERIFY2(waitForStatus(ConnectionStatus::Connected), "Failed to connect");
    QVERIFY2(!errorReceived, qPrintable(QString("Unexpected error: %1").arg(lastErrorMsg)));
    
    // 测试登出
    engine->stop();
    QVERIFY(engine->connectionStatus() == ConnectionStatus::Disconnected);
    QVERIFY(lastStatus == ConnectionStatus::Disconnected);
}

void QuoteEngineTest::testConnectionTimeout()
{
    QuoteConfig config = createTimeoutConfig();
    
    // 验证初始化
    QVERIFY2(engine->init(config), "Initialization failed");
    QVERIFY(engine->connectionStatus() == ConnectionStatus::Disconnected);
    
    // 重置错误标志
    errorReceived = false;
    lastErrorCode = 0;
    lastErrorMsg.clear();
    
    // 开始连接
    engine->start();
    
    // 等待状态变化或错误
    QElapsedTimer timer;
    timer.start();
    
    while (!errorReceived && timer.elapsed() < 10000) {
        QTest::qWait(100);
        
        // 如果状态变为已连接，则测试失败
        if (engine->connectionStatus() == ConnectionStatus::Connected) {
            QFAIL("Should not connect to invalid address");
        }
    }
    
    // 验证是否收到错误
    QVERIFY2(errorReceived, "Should receive error for invalid address");
    qDebug() << "Connection error:" << lastErrorCode << lastErrorMsg;
    
    // 验证最终状态
    QVERIFY(engine->connectionStatus() == ConnectionStatus::Disconnected);
}

void QuoteEngineTest::testSubscription()
{
    QuoteConfig config = createTestConfig();
    
    // 初始化并连接
    QVERIFY2(engine->init(config), "Initialization failed");
    engine->start();
    QVERIFY2(waitForStatus(ConnectionStatus::Connected), "Failed to connect");
    
    // 等待一下确保连接稳定
    QTest::qWait(1000);
    
    // 测试空列表订阅
    QVERIFY2(!engine->subscribe({}), "Empty subscription should fail");
    
    // 测试单个合约订阅
    tickReceived = false;
    qDebug() << "Subscribing to:" << TEST_SYMBOLS[0];
    QVERIFY2(engine->subscribe({TEST_SYMBOLS[0]}), 
             qPrintable(QString("Failed to subscribe %1").arg(TEST_SYMBOLS[0])));
             
    // 等待接收行情（增加等待时间到30秒）
    if (!waitForTick(30000)) {
        qDebug() << "No tick received after 30 seconds for" << TEST_SYMBOLS[0];
        // 不立即失败，继续测试
    }
    
    // 测试退订
    QVERIFY2(engine->unsubscribe({TEST_SYMBOLS[0]}),
             qPrintable(QString("Failed to unsubscribe %1").arg(TEST_SYMBOLS[0])));
             
    QTest::qWait(1000);  // 等待退订生效
    
    // 测试多个合约订阅
    tickReceived = false;
    qDebug() << "Subscribing to multiple symbols:" << TEST_SYMBOLS;
    QVERIFY2(engine->subscribe(TEST_SYMBOLS),
             "Failed to subscribe multiple symbols");
             
    // 等待接收行情
    if (!waitForTick(30000)) {
        qDebug() << "No tick received after 30 seconds for multiple symbols";
        // 不立即失败，继续测试
    }
    
    // 测试退订所有合约
    QVERIFY2(engine->unsubscribe(TEST_SYMBOLS),
             "Failed to unsubscribe multiple symbols");
             
    QTest::qWait(1000);
    
    // 测试订阅无效合约
    tickReceived = false;
    QVERIFY2(engine->subscribe({"INVALID"}),
             "Invalid symbol subscription should still return true");
             
    // 等待可能的错误回调
    QTest::qWait(1000);
    
    // 清理
    engine->stop();
    QVERIFY(waitForStatus(ConnectionStatus::Disconnected));
}

QTEST_MAIN(QuoteEngineTest)
#include "quote_engine_test.moc" 